package com.ruoyi.factorydata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.Seq;
import com.ruoyi.factorydata.domain.*;
import com.ruoyi.factorydata.domain.dto.ProjectProductionPlanDTO;
import com.ruoyi.factorydata.domain.vo.ProductionProjectVo;
import com.ruoyi.factorydata.domain.vo.ProjectProductionPlanVo;
import com.ruoyi.factorydata.mapper.*;
import com.ruoyi.factorydata.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 生产计划Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-26
 */
@Slf4j
@Service
public class ProjectProductionPlanServiceImpl extends ServiceImpl<ProjectProductionPlanMapper, ProjectProductionPlan> implements IProjectProductionPlanService {
    @Autowired
    private ProjectProductionPlanMapper projectProductionPlanMapper;

    @Autowired
    private IProductionProjectProductionInfoService productionProjectProductionInfoService;

    @Autowired
    private IProductionProjectService productionProjectService;

    @Autowired
    private MaterialCategoryMapper materialCategoryMapper;

    @Autowired
    private MaterialDataMapper materialDataMapper;

    @Autowired
    private WorkshopDataMapper workshopDataMapper;
    @Autowired
    @Lazy
    private IWorkOrderInfoService workOrderInfoService;
    @Autowired
    private IMaterialUnitDataService materialUnitService;
    @Autowired
    private CustomerDataMapper customerDataMapper;
    /**
     * 查询生产计划
     *
     * @param id 生产计划主键
     * @return 生产计划
     */
    @Override
    public ProjectProductionPlan selectProjectProductionPlanById(Long id) {
        ProjectProductionPlan projectProductionPlan = projectProductionPlanMapper.selectProjectProductionPlanById(id);
        ProductionProject project = productionProjectService.getById(projectProductionPlan.getProjectId());
        if(projectProductionPlan.getMaterialId()!=null){
            projectProductionPlan.setProductionOrderNumber(project.getProductionOrderNumber());
            MaterialCategory category=materialCategoryMapper.selectByMaterialId(projectProductionPlan.getMaterialId());
            projectProductionPlan.setMaterialCategoryName(category.getMaterialCategoryName());
            projectProductionPlan.setMaterialCategoryId(category.getId());
            MaterialData materialData = materialDataMapper.selectById(projectProductionPlan.getMaterialId());
            projectProductionPlan.setMaterialType(materialData.getMaterialType());
            projectProductionPlan.setManufacturingMethod(materialData.getManufacturingMethod());
        }
        if(projectProductionPlan.getWorkshopId()!=null){
            WorkshopData workshopData = workshopDataMapper.selectById(projectProductionPlan.getWorkshopId());
            projectProductionPlan.setWorkShopName(workshopData.getName());
        }
        CustomerData customerData = customerDataMapper.selectCustomerDataById(project.getCustomerId());
        projectProductionPlan.setCustomerId(project.getCustomerId());
        projectProductionPlan.setCustomerName(Optional.ofNullable(customerData).map(CustomerData::getCustomerName).orElse( null));
        projectProductionPlan.setModelNumber(project.getTemplateId());
        projectProductionPlan.setCharacterizationRequirement(project.getCharacterizationRequirement());
        projectProductionPlan.setSurfaceRequirement(project.getSurfaceRequirement());
        projectProductionPlan.setTarget(project.getTarget());
        projectProductionPlan.setProjectAttachments(project.getAttachments());
        return projectProductionPlan;
    }

    /**
     * 查询生产计划列表
     *
     * @param projectProductionPlan 生产计划
     * @return 生产计划
     */
    @Override
    public List<ProjectProductionPlan> selectProjectProductionPlanList(ProjectProductionPlan projectProductionPlan) {
        return projectProductionPlanMapper.selectProjectProductionPlanList(projectProductionPlan);
    }

    @Override
    public List<ProjectProductionPlanVo> selectProjectProductionPlanVoList(ProjectProductionPlanDTO projectProductionPlanDTO) {
        HashMap<Long, ProductionProject> projectCache = new HashMap<>();
        List<ProjectProductionPlanVo> projectProductionPlanVos = projectProductionPlanMapper.selectProjectProductionPlanListVo(projectProductionPlanDTO);
        for (ProjectProductionPlanVo projectProductionPlanVo : projectProductionPlanVos) {
            ProductionProject productionProject = productionProjectService.selectProductionProjectByIdAndCache(projectProductionPlanVo.getProjectId(), projectCache);
            MaterialUnitData materialUnitData = materialUnitService.selectMaterialUnitDataById(projectProductionPlanVo.getMaterialUnit());
            projectProductionPlanVo.setMaterialUnitName(Optional.ofNullable(materialUnitData).map(MaterialUnitData::getMaterialUnitName).orElse(""));
            Long plainActualQuantity =workOrderInfoService.sumPlainActualQuantity(projectProductionPlanVo.getId());
            projectProductionPlanVo.setActualQuantity(Optional.ofNullable(plainActualQuantity).orElse(0L)+"");
            projectProductionPlanVo.setModelNumber(Optional.ofNullable(productionProject).map(ProductionProject::getTemplateId).orElse(null));
        }
        return projectProductionPlanVos;
    }

    @Override
    public ProjectProductionPlan getLastPlanByProjectProductId(Long projectProductId) {
        return projectProductionPlanMapper.selectOne(new QueryWrapper<ProjectProductionPlan>().lambda()
                .eq(ProjectProductionPlan::getProjectProductId, projectProductId)
                .ne(ProjectProductionPlan::getStatus, 2)
                .orderByDesc(ProjectProductionPlan::getCreateTime)
                .last("LIMIT 1"));
    }

    /**
     * 新增生产计划
     *
     * @param projectProductionPlan 生产计划
     * @return 结果
     */
    @Transactional
    @Override
    public int insertProjectProductionPlan(ProjectProductionPlan projectProductionPlan) {
        // 检测计划
        checkPlain(projectProductionPlan);

        ProductionProjectVo productionProjectVo = productionProjectService.selectProductionProjectById(projectProductionPlan.getProjectId());
        projectProductionPlan.setPlanCode("PLAN_"+ Seq.getId());
        projectProductionPlan.setProjectCode(productionProjectVo.getProjectCode());
        projectProductionPlan.setStatus("0");
        projectProductionPlan.setPriority("1");
        projectProductionPlan.setCreateTime(DateUtils.getNowDate());
        long quantity = 0L;
        if(productionProjectVo.getBatchQuantity() != null && !productionProjectVo.getBatchQuantity().isBlank()){
            String[] split = productionProjectVo.getBatchQuantity().split("-");
            quantity = Long.parseLong(split[1]);
        }
        ProjectProductionPlan lastPlanByProjectProductId = getLastPlanByProjectProductId(projectProductionPlan.getProjectProductId());
        projectProductionPlan.setBatchNumber(lastPlanByProjectProductId == null || lastPlanByProjectProductId.getBatchNumber() == null ? 1 : lastPlanByProjectProductId.getBatchNumber() + 1);
        int i = projectProductionPlanMapper.insertProjectProductionPlan(projectProductionPlan);
        if (i > 0) {
            // 更新项目产品计
            boolean update = productionProjectProductionInfoService.update(new UpdateWrapper<ProductionProjectProductionInfo>().lambda()
                    .eq(ProductionProjectProductionInfo::getId, projectProductionPlan.getProjectProductId())
                    .set(ProductionProjectProductionInfo::getStatus, 1));
            boolean update1 = productionProjectService.update(new UpdateWrapper<ProductionProject>().lambda()
                    .eq(ProductionProject::getId, projectProductionPlan.getProjectId())
                    .set(ProductionProject::getStatus, 1)
                    .set(ProductionProject::getBatchQuantity, productionProjectVo.getBatchQuantity() !=  null ?
                            productionProjectVo.getProjectCode() + "-" + quantity + 1 :
                            projectProductionPlan.getProjectCode() + "-1" ));
        }
        return i;
    }

    /**
     * 检查计划是否可以创建完成
     */
    private void checkPlain(ProjectProductionPlan projectProductionPlan) {
       //已经排期数量
        ProductionProject productionProject = productionProjectService.getById(projectProductionPlan.getProjectId());
        Assert.notNull(productionProject, "项目不存在");
        ProductionProjectProductionInfo projectProductionInfo = productionProjectProductionInfoService.getOne(new LambdaQueryWrapper<ProductionProjectProductionInfo>()
                .eq(ProductionProjectProductionInfo::getProjectId, projectProductionPlan.getProjectId())
                .eq(ProductionProjectProductionInfo::getDelFlag, 0)
                .eq(ProductionProjectProductionInfo::getMaterialId, projectProductionPlan.getMaterialId())
                .last("limit 1")
        );
        Assert.notNull(projectProductionInfo, "项目生产信息不存在");
        //项目产品计划产量
        String plannedProduction = projectProductionInfo.getPlannedProduction();
        Long plannedProductionLong= StringUtils.isBlank(plannedProduction)?0L:Long.parseLong(plannedProduction);
        //项目计划已排期产量
        Long scheduledProduction = projectProductionPlanMapper.sumScheduledProductionByProject(projectProductionInfo.getProjectId(), projectProductionInfo.getMaterialId());
        scheduledProduction=Optional.ofNullable(scheduledProduction).orElse(0L);
        long plainNum = Long.parseLong(projectProductionPlan.getPlannedQuantity()) + scheduledProduction;
        Assert.isTrue(plannedProductionLong-plainNum>=0, "项目计划已排期产量不能大于计划产量");
        projectProductionPlan.setRemainingQuantity((plannedProductionLong-scheduledProduction)+"");

    }

    /**
     * 修改生产计划
     *
     * @param projectProductionPlan 生产计划
     * @return 结果
     */
    @Transactional
    @Override
    public int updateProjectProductionPlan(ProjectProductionPlan projectProductionPlan) {
        projectProductionPlan.setUpdateTime(DateUtils.getNowDate());
        // 已排程
        projectProductionPlan.setStatus("1");
        int i = projectProductionPlanMapper.updateProjectProductionPlan(projectProductionPlan);
        ProjectProductionPlan projectProductionPlan1 = projectProductionPlanMapper.selectById(projectProductionPlan.getId());
        log.info("排程:{}",projectProductionPlan1);
        if(i > 0){
            productionProjectProductionInfoService.update(new UpdateWrapper<ProductionProjectProductionInfo>().lambda()
                    .eq(ProductionProjectProductionInfo::getId, projectProductionPlan1.getProjectProductId())
                    .set(ProductionProjectProductionInfo::getStatus, "2"));
            productionProjectService.update(new UpdateWrapper<ProductionProject>().lambda()
                    .eq(ProductionProject::getId, projectProductionPlan1.getProjectId())
                    .set(ProductionProject::getStatus,"2"));
        }
        return i;
    }

    /**
     * 批量删除生产计划
     *
     * @param ids 需要删除的生产计划主键
     * @return 结果
     */
    @Override
    public int deleteProjectProductionPlanByIds(Long[] ids) {
        int i = projectProductionPlanMapper.deleteBatchIds(Arrays.stream(ids).collect(Collectors.toList()));
        return i;
    }

    /**
     * 作废生产计划
     *
     * @param projectProductId 产品主键
     * @return 结果
     */
    @Override
    public int updateStatusByProjectProductId(Long projectProductId) {
        ProjectProductionPlan lastPlanByProjectProductId = this.getLastPlanByProjectProductId(projectProductId);
        ProjectProductionPlan projectProductionPlan = new ProjectProductionPlan();
        projectProductionPlan.setId(lastPlanByProjectProductId.getId());
        projectProductionPlan.setStatus("2");
        int i =projectProductionPlanMapper.updateProjectProductionPlan(projectProductionPlan);
        return i;
    }

    /**
     * 删除生产计划信息
     *
     * @param id 生产计划主键
     * @return 结果
     */
    @Override
    public int deleteProjectProductionPlanById(Long id) {
        return projectProductionPlanMapper.deleteProjectProductionPlanById(id);
    }

    @Override
    @Transactional
    public int cancelByProject(Long projectId) {
        //获取所有未完成计划
        List<ProjectProductionPlan> productionPlanList = lambdaQuery()
                .eq(ProjectProductionPlan::getProjectId, projectId)
                .in(ProjectProductionPlan::getStatus, 0, 1, 3, 4)
                .list();
        if(CollectionUtils.isEmpty(productionPlanList)){
            log.info("暂无可取消计划");
            return 1;
        }
        for (ProjectProductionPlan projectProductionPlan : productionPlanList) {
            int cancel = cancel(projectProductionPlan.getId(),"project");
            Assert.isTrue(cancel > 0, "取消失败");
        }
        return 1;
    }

    @Override
    @Transactional
    public int cancel(Long plainId, String source) {
        Assert.notNull(plainId, "计划id不能为空");
        ProjectProductionPlan productionPlan = getById(plainId);
        Assert.notNull(productionPlan, "计划不存在");
        Assert.isTrue(Integer.parseInt(productionPlan.getStatus())!=2&&Integer.parseInt(productionPlan.getStatus())!=5, "计划无法作废");
        productionPlan.setStatus("2");
        productionPlan.setUpdateTime(DateUtils.getNowDate());
        int update = projectProductionPlanMapper.updateProjectProductionPlan(productionPlan);
        if (update>0) {
           //作废计划未完成的关联工单
            int cancel =  workOrderInfoService.cancelByPlain(productionPlan.getId(),source);
            Assert.isTrue(cancel > 0, "取消失败");
        }
        return update;
    }
}